import {
  Fog,
  Group,
  MeshBasicMaterial,
  DirectionalLight,
  AmbientLight,
  PointLight,
  Vector3,
  LineBasicMaterial,
  Color,
  MeshStandardMaterial,
  PlaneGeometry,
  PointsMaterial,
  Mesh,
  DoubleSide,
  RepeatWrapping,
  SRGBColorSpace,
  AdditiveBlending,
  NearestFilter,
  BoxGeometry,
  SpriteMaterial,
  Sprite,
} from "three"
import {
  Mini3d,
  Particles,
  FlyLine,
  PathLine,
  Label3d,
  ToastLoading,
  Plane,
  GradientShader,
  getBoundBox,
  createHistory,
} from "@/mini3d"
import { Assets } from "./map/assets"
import { ExtrudeMap } from "./map/extrudeMap"
import { DiffuseShader } from "./map/DiffuseShader"
import { Reflector } from "./map/Reflector.js"
import { InteractionManager } from "three.interactive"
import { ChildMap } from "./map-china-child"
import gsap from "gsap"

import labelArrow from "@/assets/texture/label-arrow.png"
import provincesData from "./map/provincesData"
import scatterData from "./map/scatter"
import badgesData from "./map/badgesData"

// 工具函数
function sortByValue(data) {
  return [...data].sort((a, b) => b.value - a.value)
}

// 常量配置
const SCENE_CONFIG = {
  FOG_COLOR: 0x011024,
  BACKGROUND_COLOR: 0x011024,
  DEPTH: 5,
  POINT_CENTER: [108.55, 34.32],
  FLY_LINE_CENTER: [116.41995, 40.18994],
  CAMERA_POSITION: {
    x: 0.00002366776247217723,
    y: 225.1025284992283,
    z: 0.0002238648924037432
  },
  CAMERA_TARGET: {
    x: 3.134497983573052,
    y: 126.8312346165316,
    z: 78.77649752477839
  }
}

const ANIMATION_CONFIG = {
  TIMELINE_LABELS: {
    FOCUS_MAP: 3.5,
    FOCUS_MAP_OPACITY: 4.0,
    BAR: 5.0
  },
  DURATIONS: {
    CAMERA_MOVE: 2.5,
    CAMERA_DELAY: 2,
    QUAN_ROTATION: 5,
    FOCUS_MAP: 1,
    OPACITY: 1,
    BAR_SCALE: 1,
    BAR_OPACITY: 0.5,
    LABEL: 0.5
  }
}

export class World extends Mini3d {
  constructor(canvas, config) {
    super(canvas, config)
    
    // 初始化基础配置
    this.initializeConfig()
    
    // 初始化场景
    this.initializeScene()
    
    // 初始化组件
    this.initializeComponents()
    
    // 加载资源并创建场景
    this.loadAssetsAndCreateScene()
  }

  // 初始化基础配置
  initializeConfig() {
    this.pointCenter = SCENE_CONFIG.POINT_CENTER
    this.flyLineCenter = SCENE_CONFIG.FLY_LINE_CENTER
    this.depth = SCENE_CONFIG.DEPTH
    this.clicked = false
    this.currentScene = "mainScene"
  }

  // 初始化场景
  initializeScene() {
    this.scene.fog = new Fog(SCENE_CONFIG.FOG_COLOR, 1, 500)
    this.scene.background = new Color(SCENE_CONFIG.BACKGROUND_COLOR)
    
    // 设置相机
    this.setupCamera()
    
    // 初始化环境
    this.initEnvironment()
    this.initSetting()
  }

  // 设置相机
  setupCamera() {
    const { x, y, z } = SCENE_CONFIG.CAMERA_POSITION
    this.camera.instance.position.set(x, y, z)
    this.camera.instance.near = 1
    this.camera.instance.far = 10000
    this.camera.instance.updateProjectionMatrix()
  }

  // 初始化组件
  initializeComponents() {
    this.interactionManager = new InteractionManager(
      this.renderer.instance, 
      this.camera.instance, 
      this.canvas
    )
    this.toastLoading = new ToastLoading()
    this.history = new createHistory()
    this.history.push({ name: "中国" })
    this.returnBtn = document.querySelector(".return-btn")
  }

  // 加载资源并创建场景
  loadAssetsAndCreateScene() {
    this.assets = new Assets(() => {
      this.createSceneGroups()
      this.createAllComponents()
      this.createAnimationTimeline()
    })
  }

  // 创建场景组
  createSceneGroups() {
    this.sceneGroup = new Group()
    this.mainSceneGroup = new Group()
    this.childSceneGroup = new Group()
    this.labelGroup = new Group()
    this.gqGroup = new Group() // 光圈组
    this.provinceNameGroup = new Group()
    this.badgeGroup = new Group()
    
    this.label3d = new Label3d(this)
    this.mainSceneGroup.rotateX(-Math.PI / 2)
    
    this.mainSceneGroup.add(
      this.labelGroup, 
      this.gqGroup, 
      this.provinceNameGroup, 
      this.badgeGroup
    )
    this.sceneGroup.add(this.mainSceneGroup, this.childSceneGroup)
    this.scene.add(this.sceneGroup)
  }

  // 创建所有组件
  createAllComponents() {
    this.createFloor()
    this.createRotateBorder()
    this.createModel()
    this.addEvent()
    this.createBar()
    this.createParticles()
    this.createFlyLine()
    this.createScatter()
    this.createBadgeLabel()
    this.createPathAnimate()
    this.createStorke()
  }

  // 初始化环境灯光
  initEnvironment() {
    // 环境光
    const ambientLight = new AmbientLight(0xffffff, 2)
    this.scene.add(ambientLight)
    
    // 方向光
    const directionalLight = new DirectionalLight(0xffffff, 4)
    directionalLight.position.set(-30, 6, -8)
    directionalLight.castShadow = true
    directionalLight.shadow.radius = 20
    directionalLight.shadow.mapSize.width = 1024
    directionalLight.shadow.mapSize.height = 1024
    this.scene.add(directionalLight)

    // 点光源
    this.createPointLight({
      color: "#0e81fb",
      intensity: 160,
      distance: 10000,
      x: -3,
      y: 16,
      z: -3,
    })
    this.createPointLight({
      color: "#1f5f7a",
      intensity: 100,
      distance: 100,
      x: -4,
      y: 8,
      z: 43,
    })
  }

  // 创建点光源
  createPointLight(pointParams) {
    const pointLight = new PointLight(0x1d5e5e, pointParams.intensity, pointParams.distance, 1)
    pointLight.position.set(pointParams.x, pointParams.y, pointParams.z)
    this.scene.add(pointLight)
  }

  // 初始化设置
  initSetting() {
    this.renderer.resize()
  }

  // 模型渲染
  createModel() {
    const mapGroup = new Group()
    mapGroup.name = "chinaMapGroup"
    
    const focusMapGroup = new Group()
    this.focusMapGroup = focusMapGroup
    
    // 创建地图
    const { province } = this.createProvince()
    this.provinceMesh = province
    province.setParent(focusMapGroup)

    focusMapGroup.position.set(0, 0, -5)
    focusMapGroup.scale.set(1, 1, 0)

    mapGroup.add(focusMapGroup)
    mapGroup.position.set(0, 0.2, 0)
    this.mainSceneGroup.add(mapGroup)
  }

  // 创建省份
  createProvince() {
    const mapJsonData = this.assets.instance.getResource("china")
    const topNormal = this.assets.instance.getResource("topNormal")

    topNormal.wrapS = topNormal.wrapT = RepeatWrapping

    this.provinceLineMaterial = new LineBasicMaterial({
      color: 0x2bc4dc,
      opacity: 0,
      transparent: true,
      fog: false,
    })
    
    const [topMaterial, sideMaterial] = this.createProvinceMaterial()

    this.focusMapTopMaterial = topMaterial
    this.focusMapSideMaterial = sideMaterial
    
    const province = new ExtrudeMap(this, {
      center: this.pointCenter,
      position: new Vector3(0, 0, 0.06),
      data: mapJsonData,
      depth: this.depth,
      topFaceMaterial: topMaterial,
      sideMaterial: sideMaterial,
      lineMaterial: this.provinceLineMaterial,
      renderOrder: 9,
    })
    
    this.time.on("tick", () => {
      sideMaterial.map.offset.y += 0.002
    })

    const { boxSize, box3 } = getBoundBox(province.mapGroup)

    this.eventElement = []
    province.mapGroup.children.forEach((group) => {
      group.children.forEach((mesh) => {
        if (mesh.type === "Mesh") {
          this.eventElement.push(mesh)
          this.calcUv2(mesh.geometry, boxSize.x, boxSize.y, box3.min.x, box3.min.y)
        }
      })
    })

    return { province }
  }

  // 创建省份材质
  createProvinceMaterial() {
    const topNormal = this.assets.instance.getResource("topNormal")
    topNormal.wrapS = topNormal.wrapT = RepeatWrapping
    
    const topMaterial = new MeshStandardMaterial({
      color: 0x061e47,
      emissive: 0x000000,
      map: topNormal,
      transparent: true,
      normalMap: topNormal,
      opacity: 0,
    })

    const sideMap = this.assets.instance.getResource("side")
    sideMap.wrapS = RepeatWrapping
    sideMap.wrapT = RepeatWrapping
    sideMap.repeat.set(1, 0.2)
    sideMap.offset.y += 0.01
    
    const sideMaterial = new MeshStandardMaterial({
      color: 0xffffff,
      map: sideMap,
      fog: false,
      transparent: true,
      opacity: 0,
      side: DoubleSide,
    })

    sideMaterial.onBeforeCompile = (shader) => {
      shader.uniforms = {
        ...shader.uniforms,
        uColor1: { value: new Color(0x30b3ff) },
        uColor2: { value: new Color(0x30b3ff) },
      }
      shader.vertexShader = shader.vertexShader.replace(
        "void main() {",
        `
        attribute float alpha;
        varying vec3 vPosition;
        varying float vAlpha;
        void main() {
          vAlpha = alpha;
          vPosition = position;
      `
      )
      shader.fragmentShader = shader.fragmentShader.replace(
        "void main() {",
        `
        varying vec3 vPosition;
        varying float vAlpha;
        uniform vec3 uColor1;
        uniform vec3 uColor2;
      
        void main() {
      `
      )
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <opaque_fragment>",
        /* glsl */ `
      #ifdef OPAQUE
      diffuseColor.a = 1.0;
      #endif
      
      // https://github.com/mrdoob/three.js/pull/22425
      #ifdef USE_TRANSMISSION
      diffuseColor.a *= transmissionAlpha + 0.1;
      #endif
      vec3 gradient = mix(uColor1, uColor2, vPosition.z/1.2);
      
      outgoingLight = outgoingLight*gradient;
      
      
      gl_FragColor = vec4( outgoingLight, diffuseColor.a  );
      `
      )
    }
    return [topMaterial, sideMaterial]
  }

  // 添加事件
  addEvent() {
    let objectsHover = []

    const resetMesh = (mesh) => {
      gsap.to(mesh.scale, {
        duration: 0.3,
        z: 1,
        onComplete: () => {
          mesh.traverse((obj) => {
            if (obj.isMesh) {
              obj.material[0].emissive.setHex(mesh.userData.materialEmissiveHex)
              obj.material[0].emissiveIntensity = 1
              obj.renderOrder = 9
            }
          })
        },
      })
      this.setBarMove(mesh.userData.adcode, "down")
      this.setGQMove(mesh.userData.adcode, "down")
      this.setLabelMove(mesh.userData.adcode, "down")
      this.setScatterMove(mesh.userData.adcode, "down")
    }

    const hoverMesh = (mesh) => {
      gsap.to(mesh.scale, {
        duration: 0.3,
        z: 1.5,
      })
      this.setBarMove(mesh.userData.adcode)
      this.setGQMove(mesh.userData.adcode)
      this.setLabelMove(mesh.userData.adcode)
      this.setScatterMove(mesh.userData.adcode)

      mesh.traverse((obj) => {
        if (obj.isMesh) {
          obj.material[0].emissive.setHex(0x0b112d)
          obj.material[0].emissiveIntensity = 1.5
          obj.renderOrder = 21
        }
      })
    }

    // 循环添加事件
    this.eventElement.forEach((mesh) => {
      this.interactionManager.add(mesh)
      
      mesh.addEventListener("mousedown", (event) => {
        if (this.clicked || !this.mainSceneGroup.visible) return false
        this.clicked = true
        const userData = event.target.parent.userData
        this.history.push(userData)
        this.loadChildMap(userData)
      })
      
      mesh.addEventListener("mouseup", () => {
        this.clicked = false
      })
      
      mesh.addEventListener("mouseover", (event) => {
        if (!objectsHover.includes(event.target.parent)) {
          objectsHover.push(event.target.parent)
        }

        if (this.mainSceneGroup.visible) {
          document.body.style.cursor = "pointer"
        }
        hoverMesh(event.target.parent)
      })
      
      mesh.addEventListener("mouseout", (event) => {
        objectsHover = objectsHover.filter((n) => n.userData.name !== event.target.parent.userData.name)
        resetMesh(event.target.parent)
        document.body.style.cursor = "default"
      })
    })
  }

  // 设置柱状图移动
  setBarMove(adcode, type = "up") {
    this.allBar?.forEach((barGroup) => {
      if (barGroup.userData.adcode === adcode) {
        gsap.to(barGroup.position, {
          duration: 0.3,
          z: type === "up" ? barGroup.userData.position[2] + this.depth / 2 + 0.3 : barGroup.userData.position[2],
        })
      }
    })
  }

  // 设置光圈移动
  setGQMove(adcode, type = "up") {
    this.allGuangquan?.forEach((group) => {
      if (group.userData.adcode === adcode) {
        gsap.to(group.position, {
          duration: 0.3,
          z: type === "up" ? group.userData.position[2] + this.depth / 2 + 0.3 : group.userData.position[2],
        })
      }
    })
    
    if (this.flyLineFocusGroup?.userData.adcode === adcode) {
      gsap.to(this.flyLineFocusGroup.position, {
        duration: 0.3,
        y: type === "up" 
          ? this.flyLineFocusGroup.userData.position[1] + this.depth / 2 + 0.3
          : this.flyLineFocusGroup.userData.position[1],
      })
    }
  }

  // 设置标签移动
  setLabelMove(adcode, type = "up") {
    const allLabels = [...(this.allProvinceLabel || []), ...(this.allProvinceNameLabel || [])]
    allLabels.forEach((label) => {
      if (label.userData.adcode === adcode) {
        gsap.to(label.position, {
          duration: 0.3,
          z: type === "up" ? label.userData.position[2] + this.depth / 2 + 0.3 : label.userData.position[2],
        })
      }
    })
  }

  // 设置散点图移动
  setScatterMove(adcode, type = "up") {
    this.scatterGroup?.children.forEach((sprite) => {
      if (sprite.userData.adcode === adcode) {
        gsap.to(sprite.position, {
          duration: 0.3,
          z: type === "up" ? sprite.userData.position[2] + this.depth / 2 + 0.3 : sprite.userData.position[2],
        })
      }
    })
  }

  // 加载子地图
  loadChildMap(userData) {
    this.toastLoading.show()
    this.getChildMapData(userData, (data) => {
      this.returnBtn.style.display = "block"
      this.childMap?.destroy()
      
      this.childMap = new ChildMap(this, {
        adcode: userData.adcode,
        center: userData.center,
        centroid: userData.centroid,
        childrenNum: userData.childrenNum,
        mapData: data,
        parentBoxSize: [129.00074005126953, (126.23402404785156 * 3) / 4],
      })
      
      this.childSceneGroup.add(this.childMap.instance)
      this.setMainMapVisible(false)
      this.toastLoading.hide()

      this.camera.controls.reset()
      this.currentScene = "childScene"
      this.config.setEnable(false)
    })
  }

  // 获取子地图数据
  getChildMapData(userData, callback) {
    let base_url = import.meta.env.BASE_URL
    let url = base_url + `assets/json/child-map/${userData.adcode}_full.json`

    if (userData.childrenNum === 0) {
      url = base_url + `assets/json/child-map/${userData.adcode}.json`
    }
    
    fetch(url)
      .then((res) => {
        if (!res.ok) {
          throw new Error(`HTTP error! status: ${res.status} for ${url}`);
        }
        return res.text()
      })
      .then((res) => {
        callback?.(res)
      })
      .catch(e => {
        this.toastLoading.hide()
        alert(`加载本地地图数据失败: ${url}。请确保文件存在于 'public/assets/json/child-map/' 目录下。`)
        console.error("Failed to fetch local map data:", e)
      })
  }

  // 隐藏显示主地图及标签
  setMainMapVisible(bool) {
    this.scene.getObjectByName("chinaMapGroup").visible = bool
    this.mainSceneGroup.visible = bool
    this.setLabelVisible("provinceNameGroup", bool)
    this.setLabelVisible("labelGroup", bool)
    if (bool === false) {
      this.setLabelVisible("badgeGroup", bool)
    }
  }

  // 返回上一级
  goBack() {
    this.history.undo()
    if (!this.history.getIndex()) {
      this.currentScene = "mainScene"
      this.returnBtn.style.display = "none"
      this.childMap?.destroy()
      this.childMap = null
      this.setMainMapVisible(true)
      this.setLabelVisible("labelGroup", true)
    } else {
      const userData = this.history.present
      this.loadChildMap(userData)
    }

    this.camera.controls.reset()
  }

  // 计算UV2
  calcUv2(geometry, width, height, minX, minY) {
    const positionAttribute = geometry.attributes.position
    const uvAttribute = geometry.attributes.uv

    const count = geometry.groups[0].count
    for (let i = 0; i < count; i++) {
      const x = positionAttribute.getX(i)
      const y = positionAttribute.getY(i)

      const u = (x - minX) / width
      const v = (y - minY) / height

      uvAttribute.setXY(i, u, v)
    }

    uvAttribute.needsUpdate = true
    geometry.computeVertexNormals()
  }

  // 创建柱状图
  createBar() {
    const data = sortByValue(provincesData)
    const barGroup = new Group()
    this.barGroup = barGroup

    const factor = 7
    const height = 4.0 * factor
    const max = data[0].value

    this.allBar = []
    this.allBarMaterial = []
    this.allGuangquan = []
    this.allProvinceLabel = []
    this.allProvinceNameLabel = []

    data.forEach((item, index) => {
      const geoHeight = height * (item.value / max)
      
      // 创建材质
      const material = new MeshBasicMaterial({
        color: 0xffffff,
        transparent: true,
        opacity: 0,
        depthTest: false,
        fog: false,
      })

      // 设置渐变材质
      new GradientShader(material, {
        uColor1: index < 3 ? 0xfbdf88 : 0x50bbfe,
        uColor2: index < 3 ? 0xfbdf88 : 0x50bbfe,
        size: geoHeight,
        dir: "y",
      })

      // 创建几何体
      const geo = new BoxGeometry(0.05 * factor, 0.05 * factor, geoHeight)
      geo.translate(0, 0, geoHeight / 2)
      
      const mesh = new Mesh(geo, material)
      mesh.renderOrder = 22
      
      const [x, y] = this.geoProjection(item.centroid)
      mesh.position.set(x, -y, this.depth + 0.46)
      mesh.scale.set(1, 1, 0)
      mesh.userData.name = item.name
      mesh.userData.adcode = item.adcode
      mesh.userData.position = [x, -y, this.depth + 0.46]

      // 创建光圈
      const guangQuan = this.createQuan()
      guangQuan.position.set(x, -y, this.depth + 0.46)
      guangQuan.userData.name = item.name
      guangQuan.userData.adcode = item.adcode
      guangQuan.userData.position = [x, -y, this.depth + 0.46]
      this.gqGroup.add(guangQuan)

      // 创建辉光
      const hg = this.createHUIGUANG(geoHeight, index < 3 ? 0xfffef4 : 0x77fbf5)
      mesh.add(...hg)

      barGroup.add(mesh)

      // 创建标签
      const barLabel = this.createProvinceLabel(item, index, new Vector3(x, -y, this.depth + 0.9 + geoHeight))
      const nameLabel = this.createProvinceNameLabel(item, index, new Vector3(x, -y - 1.5, this.depth + 0.4))

      this.allBar.push(mesh)
      this.allBarMaterial.push(material)
      this.allGuangquan.push(guangQuan)
      this.allProvinceLabel.push(barLabel)
      this.allProvinceNameLabel.push(nameLabel)
    })

    this.mainSceneGroup.add(barGroup)
    
    // 设置柱状图的初始可见性
    barGroup.visible = this.config.initialState?.bar === true
  }

  // 创建省份标签
  createProvinceLabel(data, index, position) {
    const label = this.label3d.create("", "provinces-label-style02", true)
    label.init(
      `<div class="provinces-label-style02 ${index < 3 ? "yellow" : ""}">
        <div class="provinces-label-style02-wrap">
          <div class="number"><span class="value">${data.value}</span><span class="unit">万人</span></div>
          <div class="no">${index + 1}</div>
        </div>
      </div>`,
      position
    )
    this.label3d.setLabelStyle(label, 0.05, "x")
    label.setParent(this.labelGroup)
    label.userData.adcode = data.adcode
    label.userData.position = [position.x, position.y, position.z]
    return label
  }

  // 创建省份名称标签
  createProvinceNameLabel(data, index, position) {
    const label = this.label3d.create("", "provinces-name-label", true)
    label.init(
      `<div class="provinces-name-label"><div class="provinces-name-label-wrap">${data.name}</div></div>`,
      position
    )
    this.label3d.setLabelStyle(label, 0.08, "x")
    label.setParent(this.provinceNameGroup)
    label.userData.adcode = data.adcode
    label.userData.position = [position.x, position.y, position.z]
    return label
  }

  // 创建辉光
  createHUIGUANG(h, color) {
    const geometry = new PlaneGeometry(1.5, h)
    geometry.translate(0, h / 2, 0)
    
    const texture = this.assets.instance.getResource("huiguang")
    texture.colorSpace = SRGBColorSpace
    texture.wrapS = RepeatWrapping
    texture.wrapT = RepeatWrapping
    
    const material = new MeshBasicMaterial({
      color: color,
      map: texture,
      transparent: true,
      opacity: 0.4,
      depthWrite: false,
      side: DoubleSide,
      blending: AdditiveBlending,
    })
    
    const mesh = new Mesh(geometry, material)
    mesh.renderOrder = 23
    mesh.rotateX(Math.PI / 2)
    
    const mesh2 = mesh.clone()
    const mesh3 = mesh.clone()
    mesh2.rotateY((Math.PI / 180) * 60)
    mesh3.rotateY((Math.PI / 180) * 120)
    
    return [mesh, mesh2, mesh3]
  }

  // 创建光圈
  createQuan() {
    const guangquan1 = this.assets.instance.getResource("guangquan1")
    const guangquan2 = this.assets.instance.getResource("guangquan2")
    const geometry = new PlaneGeometry(2, 2)

    const material1 = new MeshBasicMaterial({
      color: 0xffffff,
      map: guangquan1,
      alphaMap: guangquan1,
      opacity: 1,
      transparent: true,
      depthTest: false,
      fog: false,
      blending: AdditiveBlending,
    })
    
    const material2 = new MeshBasicMaterial({
      color: 0xffffff,
      map: guangquan2,
      alphaMap: guangquan2,
      opacity: 1,
      transparent: true,
      depthTest: false,
      fog: false,
      blending: AdditiveBlending,
    })
    
    const mesh1 = new Mesh(geometry, material1)
    const mesh2 = new Mesh(geometry, material2)
    mesh1.renderOrder = 24
    mesh2.renderOrder = 24

    mesh2.position.z -= 0.001
    mesh1.scale.set(0, 0, 0)
    mesh2.scale.set(0, 0, 0)
    
    const quanGroup = new Group()
    quanGroup.add(mesh1, mesh2)

    this.time.on("tick", (delta) => {
      mesh1.rotation.z += delta * 2
    })
    
    return quanGroup
  }

  // 设置css3d标签的隐藏显示
  setLabelVisible(labelGroup = "labelGroup", bool) {
    this[labelGroup].visible = bool
    this[labelGroup].children.forEach((label) => {
      bool ? label.show() : label.hide()
    })
  }

  // 创建底图
  createFloor() {
    const geometry = new PlaneGeometry(200, 200)
    const texture = this.assets.instance.getResource("gaoguang1")
    texture.colorSpace = SRGBColorSpace
    texture.wrapS = RepeatWrapping
    texture.wrapT = RepeatWrapping
    texture.repeat.set(1, 1)
    
    const material = new MeshBasicMaterial({
      map: texture,
      opacity: 1,
      transparent: true,
      blending: AdditiveBlending,
    })
    
    const mesh = new Mesh(geometry, material)
    mesh.rotateX(-Math.PI / 2)
    mesh.position.set(0, 0.05, 0)
    this.scene.add(mesh)

    const quanTexture = this.assets.instance.getResource("quan")
    const quan = new Mesh(
      new PlaneGeometry(250, 250),
      new MeshBasicMaterial({
        map: quanTexture,
        opacity: 1,
        transparent: true,
        blending: AdditiveBlending,
        depthTest: false,
      })
    )
    quan.rotateX(-Math.PI / 2)
    quan.position.set(0, this.depth + 2.05, 0)
    this.quan = quan
    this.scene.add(quan)
  }

  // 创建网格涟漪
  createGridRipple() {
    const geometry = new PlaneGeometry(300, 300)
    const texture = this.assets.instance.getResource("grid")
    const alphaMap = this.assets.instance.getResource("gridBlack")
    texture.wrapS = texture.wrapT = alphaMap.wrapS = alphaMap.wrapT = RepeatWrapping
    texture.repeat.set(40, 40)
    alphaMap.repeat.set(40, 40)
    
    const material = new MeshBasicMaterial({
      map: texture,
      color: 0x00ffff,
      transparent: true,
      opacity: 0.5,
      alphaMap: alphaMap,
      blending: AdditiveBlending,
    })

    const mesh = new Mesh(geometry, material)
    mesh.rotateX(-Math.PI / 2)
    const [x, y] = this.geoProjection(this.pointCenter)
    mesh.position.set(x, -y, 0.01)
    
    const mesh2 = mesh.clone()
    mesh2.material = material.clone()
    mesh2.material.opacity = 0.1
    this.scene.add(mesh, mesh2)
    
    new DiffuseShader({
      material,
      time: this.time,
      size: 300,
      diffuseColor: 0x079fe6,
      diffuseSpeed: 30,
      diffuseWidth: 20,
      diffuseDir: 2.0,
    })
  }

  // 创建镜面
  createMirror() {
    const geometry = new PlaneGeometry(200, 200)
    const groundMirror = new Reflector(geometry, {
      clipBias: 0.003,
      textureWidth: this.sizes.width,
      textureHeight: this.sizes.height,
      color: 0xb5b5b5,
      multisample: 1,
    })
    groundMirror.material.transparent = true
    groundMirror.material.opacity = 0.2
    groundMirror.position.y = -0.01
    groundMirror.rotateX(-Math.PI / 2)
    this.groundMirror = groundMirror
    this.groundMirror.visible = false
    this.scene.add(groundMirror)
  }

  // 创建旋转边框
  createRotateBorder() {
    const max = 100
    const rotationBorder1 = this.assets.instance.getResource("rotationBorder1")
    const rotationBorder2 = this.assets.instance.getResource("rotationBorder2")
    
    const plane01 = new Plane(this, {
      width: max * 1.178,
      needRotate: true,
      rotateSpeed: 0.001,
      material: new MeshBasicMaterial({
        map: rotationBorder1,
        color: 0x48afff,
        transparent: true,
        opacity: 0.2,
        depthWrite: false,
        blending: AdditiveBlending,
      }),
      position: new Vector3(0, 0.07, 0),
    })
    plane01.instance.renderOrder = 6
    plane01.instance.scale.set(0, 0, 0)
    plane01.setParent(this.scene)
    
    const plane02 = new Plane(this, {
      width: max * 1.116,
      needRotate: true,
      rotateSpeed: -0.004,
      material: new MeshBasicMaterial({
        map: rotationBorder2,
        color: 0x48afff,
        transparent: true,
        opacity: 0.4,
        depthWrite: false,
        blending: AdditiveBlending,
      }),
      position: new Vector3(0, 0.06, 0),
    })
    plane02.instance.renderOrder = 6
    plane02.instance.scale.set(0, 0, 0)
    plane02.setParent(this.scene)
    
    this.rotateBorder1 = plane01.instance
    this.rotateBorder2 = plane02.instance
  }

  // 创建粒子
  createParticles() {
    this.particles = new Particles(this, {
      num: 10,
      range: 200,
      dir: "up",
      speed: 0.1,
      material: new PointsMaterial({
        map: Particles.createTexture(),
        size: 10,
        color: 0x00eeee,
        transparent: true,
        opacity: 0.3,
        depthTest: false,
        depthWrite: false,
        vertexColors: true,
        blending: AdditiveBlending,
        sizeAttenuation: true,
      }),
    })
    this.particles.instance.position.set(0, 0, 0)
    this.particles.instance.rotation.x = -Math.PI / 2
    this.particles.setParent(this.scene)
    this.particles.enable = false
    this.particles.instance.visible = false
  }

  // 创建散点图
  createScatter() {
    this.scatterGroup = new Group()
    this.scatterGroup.visible = false
    this.mainSceneGroup.add(this.scatterGroup)
    
    const texture = this.assets.instance.getResource("arrow")
    const material = new SpriteMaterial({
      map: texture,
      color: 0xffff00,
      transparent: true,
      depthTest: false,
    })

    const scatterAllData = sortByValue(scatterData)
    const max = scatterAllData[0].value
    
    scatterAllData.forEach((data) => {
      const sprite = new Sprite(material)
      sprite.renderOrder = 23
      const scale = 2 + (data.value / max) * 1
      sprite.scale.set(scale, scale, scale)
      const [x, y] = this.geoProjection([data.lng, data.lat])
      sprite.position.set(x, -y, this.depth + 0.41)
      sprite.userData.adcode = data.adcode
      sprite.userData.position = [x, -y, this.depth + 0.41]
      this.scatterGroup.add(sprite)
    })
  }

  // 创建标牌
  createBadgeLabel() {
    this.badgeGroup.visible = false
    badgesData.forEach((data) => {
      const [x, y] = this.geoProjection(data.geometry.coordinates)
      this.createBadgeNameLabel(data, new Vector3(x, -y, this.depth + 0.92))
    })
  }

  // 创建标牌名称标签
  createBadgeNameLabel(data, position) {
    const label = this.label3d.create("", "badges-label", true)
    label.init(
      `<div class="badges-label-wrap">
        平均工资：<span>${data.value}元</span>
        <img class="icon" src="${labelArrow}" alt="" />
      </div>`,
      position
    )
    this.label3d.setLabelStyle(label, 0.1, "x")
    label.setParent(this.badgeGroup)
    label.hide()
    label.userData.adcode = data.adcode
    label.userData.position = [position.x, position.y, position.z]
    return label
  }

  // 创建飞线
  createFlyLine() {
    const texture = this.assets.instance.getResource("flyLine")
    texture.wrapS = texture.wrapT = RepeatWrapping
    texture.generateMipmaps = false
    texture.magFilter = NearestFilter
    texture.repeat.set(0.5, 1)
    
    const flyLine = new FlyLine(this, {
      centerPoint: this.flyLineCenter,
      data: provincesData,
      texture: texture,
      material: new MeshBasicMaterial({
        map: texture,
        alphaMap: texture,
        color: 0xfbdf88,
        transparent: true,
        fog: false,
        depthTest: false,
        blending: AdditiveBlending,
      }),
    })
    flyLine.setParent(this.mainSceneGroup)
    flyLine.visible = false
    flyLine.instance.position.z = this.depth + 0.4

    this.flyLineGroup = flyLine
    this.createFlyLineFocus()
  }

  // 创建飞线焦点
  createFlyLineFocus() {
    this.flyLineFocusGroup = new Group()
    this.flyLineFocusGroup.visible = false

    const [x, y] = this.geoProjection(this.flyLineCenter)
    this.flyLineFocusGroup.position.set(x, -y, this.depth + 0.47)
    this.flyLineFocusGroup.userData.name = "北京市"
    this.flyLineFocusGroup.userData.adcode = 110000
    this.flyLineFocusGroup.userData.position = [x, -y, this.depth + 0.47]
    this.mainSceneGroup.add(this.flyLineFocusGroup)
    
    const flyLineFocus = this.assets.instance.getResource("guangquan1")
    const geometry = new PlaneGeometry(5, 5)
    const material = new MeshBasicMaterial({
      color: 0xfbdf88,
      map: flyLineFocus,
      alphaMap: flyLineFocus,
      transparent: true,
      fog: false,
      depthTest: false,
      blending: AdditiveBlending,
    })
    
    const mesh = new Mesh(geometry, material)
    mesh.renderOrder = 30
    mesh.scale.set(0, 0, 0)
    const mesh2 = mesh.clone()
    mesh2.material = material.clone()
    this.flyLineFocusGroup.add(mesh, mesh2)
    
    gsap.to(mesh.material, {
      opacity: 0,
      repeat: -1,
      yoyo: false,
      duration: 1,
    })
    gsap.to(mesh.scale, {
      x: 2, y: 2, z: 2,
      repeat: -1,
      yoyo: false,
      duration: 1,
    })
    gsap.to(mesh2.material, {
      delay: 0.5,
      opacity: 0,
      repeat: -1,
      yoyo: false,
      duration: 1,
    })
    gsap.to(mesh2.scale, {
      delay: 0.5,
      x: 2, y: 2, z: 2,
      repeat: -1,
      yoyo: false,
      duration: 1,
    })
  }

  // 创建路径动画
  createPathAnimate() {
    const texture = this.assets.instance.getResource("pathLine")
    texture.wrapS = texture.wrapT = RepeatWrapping
    texture.repeat.set(8, 1)
    
    let transportPath = this.assets.instance.getResource("transportPath")
    transportPath = JSON.parse(transportPath)
    
    for (let i = 0; i < transportPath.features.length; i++) {
      const element = transportPath.features[i]
      element.geometry.coordinates = [[element.geometry.coordinates]]
    }
    
    const data = transportPath.features.map((path) => ({
      geometry: path.geometry,
    }))
    
    const pathLine = new PathLine(this, {
      data: data,
      texture: texture,
      renderOrder: 21,
      speed: 0.5,
      material: new MeshBasicMaterial({
        map: texture,
        color: 0xffffff,
        transparent: true,
        fog: false,
        opacity: 1,
        depthTest: false,
        blending: AdditiveBlending,
      }),
    })
    
    pathLine.setParent(this.mainSceneGroup)
    pathLine.visible = false
    pathLine.instance.position.z = this.depth + 0.42
    this.pathLineGroup = pathLine
  }

  // 创建轮廓
  createStorke() {
    const texture = this.assets.instance.getResource("pathLine2")
    texture.wrapS = texture.wrapT = RepeatWrapping
    texture.repeat.set(1, 1)
    
    let mapJsonData = this.assets.instance.getResource("chinaStorke")
    mapJsonData = JSON.parse(mapJsonData)

    const data = mapJsonData.features.map((path) => ({
      geometry: path.geometry,
    }))

    const pathLine = new PathLine(this, {
      data: data,
      texture: texture,
      renderOrder: 21,
      speed: 0.2,
      radius: 0.2,
      segments: 256 * 10,
      radialSegments: 4,
      material: new MeshBasicMaterial({
        color: 0x2bc4dc,
        map: texture,
        alphaMap: texture,
        fog: false,
        transparent: true,
        opacity: 1,
        blending: AdditiveBlending,
      }),
    })
    
    pathLine.setParent(this.mainSceneGroup)
    pathLine.instance.position.z = this.depth + 0.38
  }

  // 创建水印
  createWatermark() {
    const watermark = this.assets.instance.getResource("watermark")
    watermark.wrapS = RepeatWrapping
    watermark.wrapT = RepeatWrapping
    watermark.repeat.set(50, 50)
    watermark.rotation = Math.PI / 5
    
    const geometry = new PlaneGeometry(100, 100, 1)
    const material = new MeshBasicMaterial({
      map: watermark,
      transparent: true,
      opacity: 0.15,
    })
    
    const mesh = new Mesh(geometry, material)
    mesh.position.x -= 10
    mesh.position.y -= 10
    mesh.position.z -= 10
    mesh.renderOrder = 999
    this.camera.instance.add(mesh)
  }

  // 创建动画时间线
  createAnimationTimeline() {
    const tl = gsap.timeline()
    
    // 添加标签
    tl.addLabel("focusMap", ANIMATION_CONFIG.TIMELINE_LABELS.FOCUS_MAP)
    tl.addLabel("focusMapOpacity", ANIMATION_CONFIG.TIMELINE_LABELS.FOCUS_MAP_OPACITY)
    tl.addLabel("bar", ANIMATION_CONFIG.TIMELINE_LABELS.BAR)
    
    // 相机动画
    tl.add(
      gsap.to(this.camera.instance.position, {
        duration: ANIMATION_CONFIG.DURATIONS.CAMERA_MOVE,
        delay: ANIMATION_CONFIG.DURATIONS.CAMERA_DELAY,
        x: SCENE_CONFIG.CAMERA_TARGET.x,
        y: SCENE_CONFIG.CAMERA_TARGET.y,
        z: SCENE_CONFIG.CAMERA_TARGET.z,
        ease: "circ.out",
        onComplete: () => this.camera.controls.saveState(),
      })
    )

    tl.add(
      gsap.to(this.quan.rotation, {
        duration: ANIMATION_CONFIG.DURATIONS.QUAN_ROTATION,
        z: -2 * Math.PI,
      }),
      "-=2"
    )

    tl.add(
      gsap.to(this.focusMapGroup.position, {
        duration: ANIMATION_CONFIG.DURATIONS.FOCUS_MAP,
        x: 0, y: 0, z: 0,
      }),
      "focusMap"
    )
    
    tl.add(
      gsap.to(this.focusMapGroup.scale, {
        duration: ANIMATION_CONFIG.DURATIONS.FOCUS_MAP,
        x: 1, y: 1, z: 1,
        ease: "circ.out",
      }),
      "focusMap"
    )

    this.provinceMesh.mapGroup.traverse((obj) => {
      if (obj.isMesh) {
        tl.add(
          gsap.to(obj.material[0], {
            duration: ANIMATION_CONFIG.DURATIONS.OPACITY,
            opacity: 1,
            ease: "circ.out",
          }),
          "focusMapOpacity"
        )
        tl.add(
          gsap.to(obj.position, {
            duration: ANIMATION_CONFIG.DURATIONS.OPACITY,
            x: 0, y: 0, z: 0,
            ease: "circ.out",
          }),
          "focusMapOpacity"
        )
      }
    })
    
    tl.add(
      gsap.to(this.focusMapSideMaterial, {
        duration: ANIMATION_CONFIG.DURATIONS.OPACITY,
        opacity: 1,
        ease: "circ.out",
        onComplete: () => {
          this.createMirror()
          this.createGridRipple()
        },
      }),
      "focusMapOpacity"
    )

    tl.add(
      gsap.to(this.provinceLineMaterial, {
        duration: 0.5,
        delay: 0.3,
        opacity: 1,
      }),
      "focusMapOpacity"
    )

    tl.add(
      gsap.to(this.rotateBorder1.scale, {
        delay: 0.3,
        duration: ANIMATION_CONFIG.DURATIONS.OPACITY,
        x: 1, y: 1, z: 1,
        ease: "circ.out",
      }),
      "focusMapOpacity"
    )
    
    tl.add(
      gsap.to(this.rotateBorder2.scale, {
        duration: ANIMATION_CONFIG.DURATIONS.OPACITY,
        delay: 0.5,
        x: 1, y: 1, z: 1,
        ease: "circ.out",
      }),
      "focusMapOpacity"
    )
    
    // 只有当柱状图默认启用时才播放动画
    if (this.config.initialState?.bar === true) {
      this.allBar.forEach((item, index) => {
        tl.add(
          gsap.to(item.scale, {
            duration: ANIMATION_CONFIG.DURATIONS.BAR_SCALE,
            delay: 0.05 * index,
            x: 1, y: 1, z: 1,
            ease: "circ.out",
          }),
          "bar"
        )
      })
    }
    
    // 只有当柱状图默认启用时才播放材质动画
    if (this.config.initialState?.bar === true) {
      this.allBarMaterial.forEach((item, index) => {
        tl.add(
          gsap.to(item, {
            duration: ANIMATION_CONFIG.DURATIONS.BAR_OPACITY,
            delay: 0.05 * index,
            opacity: 1,
            ease: "circ.out",
          }),
          "bar"
        )
      })
    }
    
    // 只有当柱状图默认启用时才播放标签动画
    if (this.config.initialState?.bar === true) {
      this.allProvinceLabel.forEach((item, index) => {
        const element = item.element.querySelector(".provinces-label-style02-wrap")
        const number = item.element.querySelector(".number .value")
        const numberVal = Number(number.innerText)
        const numberAnimate = { score: 0 }
        
        tl.add(
          gsap.to(element, {
            duration: ANIMATION_CONFIG.DURATIONS.LABEL,
            delay: 0.05 * index,
            translateY: 0,
            opacity: 1,
            ease: "circ.out",
          }),
          "bar"
        )
        
        const textAnimation = gsap.to(numberAnimate, {
          duration: ANIMATION_CONFIG.DURATIONS.LABEL,
          delay: 0.05 * index,
          score: numberVal,
          onUpdate: () => {
            number.innerText = numberAnimate.score.toFixed(0)
          },
        })
        tl.add(textAnimation, "bar")
      })
    }
    
    this.allProvinceNameLabel.forEach((item, index) => {
      const element = item.element.querySelector(".provinces-name-label-wrap")
      tl.add(
        gsap.to(element, {
          duration: ANIMATION_CONFIG.DURATIONS.LABEL,
          delay: 0.05 * index,
          translateY: 0,
          opacity: 1,
          ease: "circ.out",
        }),
        "bar"
      )
    })
    
    this.allGuangquan.forEach((item, index) => {
      tl.add(
        gsap.to(item.children[0].scale, {
          duration: ANIMATION_CONFIG.DURATIONS.LABEL,
          delay: 0.05 * index,
          x: 1, y: 1, z: 1,
          ease: "circ.out",
        }),
        "bar"
      )
      tl.add(
        gsap.to(item.children[1].scale, {
          duration: ANIMATION_CONFIG.DURATIONS.LABEL,
          delay: 0.05 * index,
          x: 1, y: 1, z: 1,
          ease: "circ.out",
        }),
        "bar"
      )
    })
    
    // 根据初始状态设置标签可见性
    tl.call(() => {
      if (this.config.initialState?.bar === false) {
        this.setLabelVisible("labelGroup", false)
      }
    })
  }

  // 更新
  update() {
    super.update()
    this.stats?.update()
    this.interactionManager?.update()
  }

  // 销毁
  destroy() {
    super.destroy()
    this.label3d?.destroy()
    this.stats?.dom && document.body.removeChild(this.stats.dom)
    this.groundMirror?.dispose()
    this.toastLoading?.destroy()
    this.childMap?.destroy()
  }
}
